package org.cheniy.domain.strategy.service.raffle;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.cheniy.domain.strategy.model.entity.RaffleAwardEntity;
import org.cheniy.domain.strategy.model.entity.RaffleFactorEntity;
import org.cheniy.domain.strategy.model.entity.StrategyAwardEntity;
import org.cheniy.domain.strategy.repository.IStrategyRepository;
import org.cheniy.domain.strategy.service.IRaffleStrategy;
import org.cheniy.domain.strategy.service.armory.IStrategyDispatch;
import org.cheniy.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import org.cheniy.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import org.cheniy.types.enums.ResponseCode;
import org.cheniy.types.exception.AppException;

import java.util.Date;

/**
 * @author cheniy
 * @description 抽象策略抽象类-模版方法
 * @create 2025/3/6 12:08
 */
@Slf4j
public abstract class AbstractRaffleStrategy implements IRaffleStrategy {

    // 策略仓储服务 -> domain层像一个大厨，仓储层提供米面粮油
    protected IStrategyRepository iStrategyRepository;
    // 策略调度服务 -> 只负责抽奖处理，通过新增接口的方式，隔离职责，不需要使用方关心或者调用抽奖的初始化
    protected IStrategyDispatch iStrategyDispatch;

    protected DefaultChainFactory defaultChainFactory;
    protected DefaultTreeFactory defaultTreeFactory;

    public AbstractRaffleStrategy(IStrategyRepository iStrategyRepository, IStrategyDispatch iStrategyDispatch, DefaultChainFactory defaultChainFactory, DefaultTreeFactory defaultTreeFactory) {
        this.iStrategyRepository = iStrategyRepository;
        this.iStrategyDispatch = iStrategyDispatch;
        this.defaultChainFactory = defaultChainFactory;
        this.defaultTreeFactory = defaultTreeFactory;
    }

    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {


        // 抽奖流程安排
        // 1. 参数校验
        String userId = raffleFactorEntity.getUserId();
        Long strategyId = raffleFactorEntity.getStrategyId();
        if (null == strategyId || StringUtils.isBlank(userId)) {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }


        // 2. 责任链抽奖计算【这步 拿到的是初步的抽奖ID，之后需要根据ID处理抽奖】注意；黑名单、权重等非默认抽奖的直接返回抽奖结果
        DefaultChainFactory.StrategyAwardVO chainStrategyAwardVO = this.raffleLogicChain(userId, strategyId);
        log.info("抽奖策略计算-责任链 {} {} {} {}", userId, strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getLogicModel());
        // 黑名单、权重等非默认抽奖的直接返回抽奖id
        // if (!DefaultChainFactory.LogicModel.RULE_DEFAULT.getCode().equals(chainStrategyAwardVO.getLogicModel())){
        //
        //
        //     return buildRaffleAwardEntity(strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getAwardRuleValue());
        //
        // }

        // 3. 规则树抽奖过滤【奖品ID，会根据抽奖次数判断、库存判断、兜底返回最终的可获得奖品信息】
        DefaultTreeFactory.StrategyAwardVO treeStrategyAwardVO = raffleLogicTree(userId, strategyId, chainStrategyAwardVO.getAwardId(), raffleFactorEntity.getEndDateTime());
        log.info("抽奖策略计算-规则树 {} {} {} {}", userId, strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue());
        // 非兜底奖品放行，兜底奖品返回积分


        // 4. 未被拦截则放行
        return buildRaffleAwardEntity(strategyId,treeStrategyAwardVO.getAwardId(),treeStrategyAwardVO.getAwardRuleValue());

    }

    /**
     * 构建返回奖品信息RaffleAwardEntity
     *
     * @param strategyId
     * @param awardId
     * @param awardConfig 规则节点中对应规则的值 次数锁-1，幸运奖-101:1,100 库存扣减-null
     * @return
     */
    private RaffleAwardEntity buildRaffleAwardEntity(Long strategyId,Integer awardId, String awardConfig){
        StrategyAwardEntity raffleAwardEntity =iStrategyRepository.queryStrategyAwardEntity(strategyId,awardId);
        return  RaffleAwardEntity.builder()
                .awardId(raffleAwardEntity.getAwardId())
                .awardConfig(awardConfig)
                .sort(raffleAwardEntity.getSort())
                .awardTitle(raffleAwardEntity.getAwardTitle())
                .build();
    }


    /**
     * 抽奖计算，责任链抽象方法
     * @param userId
     * @param strategyId
     * @return
     */
    public abstract DefaultChainFactory.StrategyAwardVO raffleLogicChain(String userId, Long strategyId);

    /**
     * 抽奖结果过滤，决策树抽象方法
     * @param userId
     * @param strategyId
     * @param awardId
     * @return 过滤结果【奖品ID，会根据抽奖次数判断、库存判断、兜底兜里返回最终的可获得奖品信息】
     */
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId);
    /**
     * 抽奖结果过滤，决策树抽象方法
     *
     * @param userId      用户ID
     * @param strategyId  策略ID
     * @param awardId     奖品ID
     * @param endDateTime 活动结束时间 - 用于设定缓存有效期
     * @return 过滤结果【奖品ID，会根据抽奖次数判断、库存判断、兜底兜里返回最终的可获得奖品信息】
     */
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId, Date endDateTime);


}
